﻿using NM.Module.SafeResponse.Middleware.Configurations;
using FrameworkCore.DI;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;

namespace NM.Module.SafeResponse.Middleware.EncryptHelpers;

/// <summary>
/// 对称加密提供者
/// </summary>
public class AESProvider : ITransientDependency
{
    private readonly IOptions<SecretSettings> _optSecretSettings;

    public AESProvider(IOptions<SecretSettings> optSecretSettings)
    {
        _optSecretSettings = optSecretSettings;
    }

    public SecretSettings SecretSettings => _optSecretSettings.Value;

    /// <summary>
    /// 生成Key和IV
    /// </summary>
    /// <returns></returns>
    public (string key, string iv) GenerateKeyWithIV()
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.GenerateKey();
            aesAlg.GenerateIV();
            string keyString = Convert.ToBase64String(aesAlg.Key);
            string ivString = Convert.ToBase64String(aesAlg.IV);
            return (keyString, ivString);
        }
    }

    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="plainText"></param>
    /// <param name="key"></param>
    /// <param name="iv"></param>
    /// <returns></returns>
    public string Encrypt(string plainText, string? key = default, string? iv = default)
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Convert.FromBase64String(key ?? _optSecretSettings.Value.AESSecret.Key);
            aesAlg.IV = Convert.FromBase64String(iv ?? _optSecretSettings.Value.AESSecret.IV);

            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }
                    return Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
        }
    }

    /// <summary>
    /// 解密
    /// </summary>
    /// <param name="cipherText"></param>
    /// <param name="key"></param>
    /// <param name="iv"></param>
    /// <returns></returns>
    public string Decrypt(string cipherText, string? key = default, string? iv = default)
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Convert.FromBase64String(key ?? _optSecretSettings.Value.AESSecret.Key);
            aesAlg.IV = Convert.FromBase64String(iv ?? _optSecretSettings.Value.AESSecret.IV);

            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        return srDecrypt.ReadToEnd();
                    }
                }
            }
        }
    }
}
